//
//  MoyaEx.swift
//  XTools
//
//  Created by Xwg on 2017/7/14.
//  Copyright © 2017年 Yelopack. All rights reserved.
//
//  MARK: - Moya扩展

import RxSwift
import Moya
import HandyJSON

// MARK: - RxSwift 扩展
extension PrimitiveSequence where TraitType == SingleTrait, ElementType == Response {
    public func mapModel<T>(_ type: T.Type) -> Observable<MoyaResult<T>> {
        return asObservable().mapModel(type)
    }
}

extension ObservableType where E == Response {
    
    public func mapModel<T>(_ type: T.Type) -> Observable<MoyaResult<T>> {
        return flatMap { response -> Observable<MoyaResult<T>> in
            return Observable.just(try response.mapModel(type))
            
//            let model = try response.mapModel(type)
//            return Observable.create { observable -> Disposable in
//                dPrint("+++++++++++++++++")
//                DispatchQueue.main.asyncAfter(deadline: .now() + 5, execute: {
//                    dPrint("---------------")
//                    observable.onNext(model)
//                    observable.onCompleted()
//                })
//
//                return Disposables.create()
//            }
        }
    }
}

extension MoyaProvider {
    
    @discardableResult
    func requestModel<Model>(_ target: Target, completion: @escaping (MoyaResult<Model>) -> Void) -> Cancellable {
        return request(target) { result in
            switch result {
            case .success(let resp):
                completion(resp.mapModel(Model.self))
            case .failure(let err):
                completion(.failure(err.errorCode, kErrmsg_NetworkAnomaly))
            }
        }
    }
}

extension Response {
    
    func mapModel<T>(_ type: T.Type) -> MoyaResult<T> {
        
        guard let _ = try? filterSuccessfulStatusCodes() else {
            return .failure(statusCode, "服务器访问失败")
        }
        
        // 转换成 json
        guard JSONSerialization.isValidJSONObject(data) else {
            return .failure(-1, kErrmsg_DataInvalid)
        }
        
        let jsonObj = try! JSONSerialization.jsonObject(with: data, options: .mutableLeaves)
        let jsonData = try! JSONSerialization.data(withJSONObject: jsonObj, options: .prettyPrinted)
        
        guard let jsonString = String(data: jsonData, encoding: .utf8) else {
            return .failure(-1, kErrmsg_DataInvalid)
        }
        
        dPrint(jsonString)
        
        guard let model = JSONDeserializer<BaseData<T>>.deserializeFrom(json: jsonString)?.data else {
            return .failure(-1, kErrmsg_DataInvalid)
        }
        
        return .success(model)
    }
}

struct BaseData<T>: HandyJSON {
    var errcode: Int = -1
    var errmsg: String = NSLocalizedString("Network_errorCode_null", comment:"")
    var data: T? = nil
}

struct BaseDataList<T>: HandyJSON {
    var list: [T] = []
    var pages: Int = 0
    var isLastPage: Bool = false
}

public enum MoyaResult<T> {
    case success(T)
    case failure(Int, String)
}
